package com.example.om_export.app.upload.service;


import com.example.om_export.app.upload.dao.SysAttachmentMapper;
import com.example.om_export.app.upload.entity.SysAttachment;
import com.example.om_export.common.entity.CustomVar;
import com.example.om_export.common.entity.Result;
import com.example.om_export.common.utils.BaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;

/**
 * 上传相关接口
 * @author wb-ycl473317
 */
@Service
public class UploadService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private CustomVar customVar;

    @Autowired
    private SysAttachmentMapper sysAttachmentMapper;

    /**
     * 保存附件
     * @param files
     * @param attType
     * @return
     */
    public Result save(MultipartFile[] files, String docunid, String attType) {
        // 获取保存文件的根目录
        String rootPath = customVar.getUploadPath();
        // 文件相对目录
        String filePath = customVar.getAttachmentDir()+LocalDate.now().toString()+"/";
        if(BaseUtil.isEmpty(docunid)){
            docunid=BaseUtil.uuid();
        }
        //记录已经保存的附件id
        List<String> sysAttachmentIds = new LinkedList<>();
        Map<String,Object> sysAttachmentUrl = new HashMap<>(files.length);
        //开始保存文件
        for (MultipartFile file : files) {
            SysAttachment sysAttachment = new SysAttachment();
            sysAttachment.setId(BaseUtil.uuid());
            sysAttachment.setDocunid(docunid);
            sysAttachment.setFileName(file.getOriginalFilename());
            sysAttachment.setFilePath(filePath);
            sysAttachment.setFileSize(String.valueOf(file.getSize()));

            String oriName = file.getOriginalFilename();
            if(oriName!=null){
                sysAttachment.setFileType(oriName.substring(oriName.lastIndexOf(".")));
            }

            // 刚新增的文件状态为临时，会被定期清除
            sysAttachment.setDelState(customVar.getQuiet());
            sysAttachment.setAttType(attType);
            sysAttachment.setCreated(new Date());
//            sysAttachment.setCreater(UserUtil.getUser()==null? "":UserUtil.getUser().getId());
            sysAttachmentMapper.insert(sysAttachment);
            sysAttachmentIds.add(sysAttachment.getId());
            sysAttachmentUrl.put(sysAttachment.getId(),sysAttachment.generatePath());
            // 文件落盘
            File fullPath = new File(rootPath+filePath);
            if(!fullPath.exists()){
                fullPath.mkdirs();
            }
            try {
                file.transferTo(new File(fullPath,sysAttachment.getId()+sysAttachment.getFileType()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return Result.success(docunid).addOther("sysAttachmentIds",sysAttachmentIds).addOther("paths",sysAttachmentUrl);
    }

    /**
     * 更新附件
     * 根据新增和删除的数组更新附件表
     * 附件都是选中后就上传的此时状态为 1（不可用），通过这个方法将附件变为有效或无效
     * @param addIds 需要新增的附件
     * @param delIds 需要删除的附件
     */
    public Result update(List<String> addIds,List<String> delIds){
        if(delIds!=null){
            deleteByIds(delIds);
        }
        if(addIds!=null){
            activeByIds(addIds);
        }
        return Result.success();
    }

    /**
     * 根据 docunid将对应附件状态改为可用
     * @param docunid
     * @return
     */
    public Result active(String docunid) {
        int r = sysAttachmentMapper.updateDelStateByDocunId(docunid,customVar.getActive());
        return Result.byRow(r);
    }

    /**
     * 根据附件的id 将数据改为可用
     * @param ids
     * @return
     */
    public Result activeByIds(List<String> ids){
        if(ids==null||ids.size()==0){
            return Result.byRow(-1);
        }
        int r = sysAttachmentMapper.updateDelStateByIds(ids,customVar.getActive());
        return Result.byRow(r);
    }

    /**
     * 根据 docunid将对应附件状态改为不可用
     * @param docunid
     * @return
     */
    public Result quiet(String docunid) {
        int r = sysAttachmentMapper.updateDelStateByDocunId(docunid,customVar.getQuiet());
        return Result.byRow(r);
    }

    /**
     * 根据id删除附件，同时包括文件
     * @return
     */
    public int deleteByIds(List<String> ids){
        if(ids==null||ids.size()==0){
            return -1;
        }
        List<SysAttachment> list = sysAttachmentMapper.selectByIds(ids);
        if(list==null){
            return -1;
        }
        int r = sysAttachmentMapper.deleteByIds(ids);
        delFile(list);
        return r;
    }

    /**
     * 根据附件记录的集合删除附件
     * @param sysAttachments
     */
    public int delFile(List<SysAttachment> sysAttachments){
        int count=0;
        for (SysAttachment sysAttachment : sysAttachments) {
            count+=delFile(sysAttachment)?1:0;
        }
        return count;
    }

    private boolean delFile(SysAttachment sysAttachment) {
        return delFile(sysAttachment.getFilePath()+sysAttachment.getId()+sysAttachment.getFileType());
    }

    /**
     * 根据文件的相对路径删除附件
     * @param path 根据表数据拼接出来的路径 不包括磁盘上的根目录位置
     * @return
     */
    public boolean delFile(String path){
        File file = new File(customVar.getUploadPath()+path);
        return file.delete();
    }

    /**
     * 根据附件id删除附件
     * @param id
     * @return
     */
    public Result delete(String id) {
        int r = sysAttachmentMapper.deleteByPrimaryKey(id);
        delFile(sysAttachmentMapper.selectByPrimaryKey(id));
        return Result.byRow(r);
    }

    /**
     * 清理附件文件
     * 删除掉附件表中del_state=1 的记录和对应的文件
     */
    public void cleanFile(){
        log.info("开始清理附件临时文件");
        int delState = 1;
        // 查询出来所有临时附件
        List<SysAttachment> list = sysAttachmentMapper.selectByDelState(delState);
        // 删除附件记录
        int r = sysAttachmentMapper.deleteByDelState(delState);
        // 删除文件
        int count = delFile(list);
        log.info("清理结果：附件记录{}条，删除硬盘文件{}个",r,count);
    }
}
